Velocity vs. Maintainability
Let's discuss how you can make the right tradeoff between the velocity and maintainability of the project.
Tradeoffs change with project maturity#
Most people today understand both the intended spirit and unintended consequences of “Move fast and break things.” However, what is less well understood is how tradeoffs change as project maturity changes.
When you are conducting R&D in a small startup, you should absolutely move fast. The consequence of failure is minimal, so the value of systems and processes is low. However, when you are pushing a code change to a massive infrastructure system, one tiny mistake can cause hundreds of millions of losses in seconds. The results get even direr when human lives are at stake.
What applies to project maturity also applies to developer maturity.
Make the right tradeoffs#
As a junior, your velocity and impact are low. Your main task is to get code working with seniors to catch you when you fall. Improving your own velocity is a perfectly reasonable thing to prioritize. If you do anything that isn’t up to code standards, your seniors will hold you accountable.
Unfortunately, this luxury goes away when you become a senior. Now, you are expected to be able to independently ship. Part of that independence comes from the trust that you will establish by making the right tradeoffs between velocity and maintainability. It’s less about pushing the limits of what you can do and more about creating systems that last under forwarding assumptions. After all, anyone can build systems that are twice as complex as they can easily maintain.
Avoid future problems#
If you don’t write maintainable software, you are just causing future problems for yourself. So:
Do testing#
Instead of testing because you’re told to, you test because it’s the only way to scale yourself. You also are much more hesitant to write fragile tests because they cause more work than they save. They test implementation detail and hurt migrations (more on migrations below). You insist that either production code be merged in together with tests for that code, or not at all, except under specifically enumerated emergencies.
Avoid bugs in the first place#
Instead of only fixing bugs after you create them, you work to avoid them in the first place. You lean on your past scars, use tooling, and make careful choices in everything from API design to variable naming.
Document your code#
You document and comment on your code. Not just for your future self, but also for the people who take over the code when you move on to bigger, better things.
⚠️ Warning: If you fall in love with writing perfect code, your velocity can slow to unacceptable levels. Remember that done is better than perfect, and good enough is better than best.
Optimize for velocity over maintainability#
However, most organizations create incentives that optimize velocity over maintainability. One way to tell is whether the equal effort is spent learning from and tracking mistakes as is spent shipping features. A good first step is to establish a culture of blameless post-mortem (you can borrow AWS’s incident post-mortem template as a starting point).
It’s fine to make mistakes, but it is not fine to repeat mistakes. Critical incidents should act as brakes on velocity. Don’t view this as a step backward. Your job isn’t just building features; you’re also building a system to last, scale, and recover from anything. If you make your postmortems public, it can greatly increase customer trust and help improve the industry.
Solutions vs. Patterns
Technical Debt